package net.atomarrow.monitor;

import java.io.File;

import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationObserver;

import net.atomarrow.configs.Config;
import net.atomarrow.configs.DbConfig;
import net.atomarrow.controllers.Controller;
import net.atomarrow.db.orm.OrmContext;
import net.atomarrow.db.pool.IDataSource;
import net.atomarrow.domains.Domain;
import net.atomarrow.ioc.ApplicationContext;
import net.atomarrow.mapping.ActionMapping;
import net.atomarrow.services.Service;

/**
 * 监控Controller和Service类 变动，一旦变动就重新加载，让变动生效
 * 需要配合Jrebel使用
 * @author Boolone
 *
 */
public class DefaultFileAlteratinListener implements FileAlterationListener {

	@Override
	public void onStop(FileAlterationObserver observer) {
	}

	@Override
	public void onStart(FileAlterationObserver observer) {
//		System.out.println("start monitor class change...");
	}

	@Override
	public void onFileDelete(File file) {
		System.out.println("类删除："+file.getName());
		try {
			Class clazz=loadFromFile(file);
			ApplicationContext.remove(clazz);
			if(Controller.class.isAssignableFrom(clazz)){
                ApplicationContext.get(ActionMapping.class).removeActions(clazz);
            }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void onFileCreate(File file) {
		System.out.println("类创建："+file.getName());
		if(file.getName().endsWith("class")){
			try {
				Class clazz=loadFromFile(file);
				if(Controller.class.isAssignableFrom(clazz)){
                    reloadController(clazz);
                }
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

	@Override
	public void onFileChange(File file) {
		System.out.println("类修改："+file.getName());
		if(file.getName().endsWith("class")){
			try {
				Class clazz=loadFromFile(file);
				//Controller类
				if(Controller.class.isAssignableFrom(clazz)){
                    reloadController(clazz);
                }
				//Config
				if(Config.class.isAssignableFrom(clazz)){
					reloadConfig(clazz);
				}
				//Domain
				if(Domain.class.isAssignableFrom(clazz)){
					OrmContext.reloadDomain(clazz.getSimpleName(), clazz);
				}
				//Service
				if(Service.class.isAssignableFrom(clazz)){
					reloadService(clazz);
				}
				SerializeConfig.getGlobalInstance().put(clazz, null);
				ParserConfig.getGlobalInstance().putDeserializer(clazz, null);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

	public void reloadService(Class clazz){
		ApplicationContext.inject(ApplicationContext.get(clazz));
	}

	public void reloadConfig(Class clazz){
		IDataSource source=ApplicationContext.get(Config.class).configDbPool();
		//先把原来的连接池关闭
		if(source!=null){
			source.stop();
		}
		Config config;
		try {
			config = (Config) clazz.newInstance();
			ApplicationContext.load(Config.class,config);
			config.configOrmBean();
			DbConfig dbConfig=ApplicationContext.get(DbConfig.class);
			dbConfig.loadConfig(config);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void reloadController(Class clazz) throws Exception{
		ActionMapping actionMapping=ApplicationContext.get(ActionMapping.class);
		actionMapping.removeActions(clazz);
		actionMapping.loadActions(clazz);
        ApplicationContext.load(clazz.newInstance());
	}
	/**
     *
     * @param file
     * @return
     * @throws Exception
     */
    public  Class loadFromFile(File file) throws Exception{
		String classPath=file.getPath();
		classPath=classPath.substring(classPath.indexOf("classes")+8, classPath.lastIndexOf("."))
				.replaceAll("\\"+File.separator, ".");
		Class clazz=Class.forName(classPath);
		return clazz;
    }
	@Override
	public void onDirectoryDelete(File directory) {
	}

	@Override
	public void onDirectoryCreate(File directory) {
	}

	@Override
	public void onDirectoryChange(File directory) {
	}

}
